using System;
using System.Transactions;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.ConnectionPool;
using OracleInternal.ServiceObjects;

namespace OracleInternal.MTS
{
	internal abstract class MTSTxnRM : ISinglePhaseNotification, IEnlistmentNotification
	{
		internal class TxnBranchesByUserAuth : TxnBranchesByString
		{
		}

		internal static int MaxNumOfBranches = 32;

		internal Guid m_RMGuid = Guid.NewGuid();

		internal Transaction m_sysTxn;

		internal string m_txnLocalID = string.Empty;

		internal SyncQueueList<ConnectionString> m_connStrs = new SyncQueueList<ConnectionString>();

		internal string m_serviceName;

		internal string m_pdbName;

		internal string m_dbEasyConnectName = string.Empty;

		internal string m_txnAffInstanceName = string.Empty;

		protected RMTxnState m_state;

		internal EnlistedState m_enlistedState = EnlistedState.Local;

		internal bool m_bIgnoreIsolationLvl;

		internal int m_branchNum = 1;

		private MTSTxnBranches m_txnBranches = new MTSTxnBranches();

		private MTSTxnBranches m_NotUsedBranches = new MTSTxnBranches();

		private MTSFreeTxnBranches m_freeTxnBranches = new MTSFreeTxnBranches();

		private MTSTxnRMWorker m_RMWorker;

		private object m_lock = new object();

		private object m_branchLock = new object();

		internal object m_txnAffinityLock = new object();

		internal bool m_bIsCCP = true;

		internal MTSTxnRM(bool bIsCCP)
		{
			m_bIsCCP = bIsCCP;
		}

		~MTSTxnRM()
		{
			m_txnBranches.ClearBranches();
			m_freeTxnBranches.ClearBranches();
			m_NotUsedBranches.ClearBranches();
		}

		internal abstract void ReleaseRPs(SyncQueueList<ConnectionString> csList, Transaction txn);

		internal abstract void ReleaseRP(ConnectionString cs, Transaction txn);

		internal virtual void UnRegisteringTxnEvent(Transaction txn)
		{
		}

		internal virtual void MTSTransactionCompleted(object sender, TransactionEventArgs e)
		{
		}

		internal void Initialize(string easyConnectName, string serviceName, string pdbName, Transaction txn)
		{
			if (ProviderConfig.m_bTraceLevelPrivate_NoTrace)
			{
				string[] array = new string[1];
				string[] obj = new string[6]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = " RMState = ";
				obj[3] = m_state.ToString();
				obj[4] = " Local TxnID = ";
				obj[5] = txn.TransactionInformation.LocalIdentifier;
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Initialize, array);
			}
			m_dbEasyConnectName = easyConnectName;
			m_serviceName = serviceName;
			m_pdbName = pdbName;
			m_sysTxn = txn.Clone();
			m_txnLocalID = m_sysTxn.TransactionInformation.LocalIdentifier;
			m_RMWorker = new MTSTxnRMWorker();
			if (ProviderConfig.m_bTraceLevelPrivate_NoTrace)
			{
				string[] array2 = new string[1];
				string[] obj2 = new string[6]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj2[1] = rMGuid.ToString();
				obj2[2] = " RMState = ";
				obj2[3] = m_state.ToString();
				obj2[4] = " Local TxnID = ";
				obj2[5] = txn.TransactionInformation.LocalIdentifier;
				array2[0] = string.Concat(obj2);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Initialize, array2);
			}
		}

		internal void Reset()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Reset, $"MTSTxnRM : {GetHashCode()} RM Guid = {m_RMGuid} RMState = {m_state} Local Txn ID = {m_txnLocalID}");
			}
			m_state = RMTxnState.Invalid;
			m_dbEasyConnectName = string.Empty;
			m_txnAffInstanceName = string.Empty;
			m_enlistedState = EnlistedState.Local;
			m_branchNum = 1;
			m_txnBranches.ClearBranches();
			m_NotUsedBranches.ClearBranches();
			m_freeTxnBranches.ClearBranches();
			m_connStrs.Clear();
			m_RMWorker = null;
			m_txnLocalID = string.Empty;
			m_bIgnoreIsolationLvl = false;
			if (ProviderConfig.m_bTraceLevelPrivate_NoTrace)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Reset, $"MTSTxnRM : {GetHashCode()} RM Guid = {m_RMGuid} RMState = {m_state} Local Txn ID = {m_txnLocalID}");
			}
		}

		internal void ReleaseRM()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.ReleaseRM);
			}
			try
			{
				ReleaseRPs(m_connStrs, m_sysTxn);
				m_NotUsedBranches.ClearBranches();
				m_txnBranches.ClearBranches();
				m_freeTxnBranches.ClearBranches();
				MTSProxyPool.ReleaseRM(m_bIsCCP, m_dbEasyConnectName, m_sysTxn);
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.ReleaseRM);
				}
			}
		}

		public void SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				string[] obj = new string[8]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = "\tRMState = ";
				obj[3] = m_state.ToString();
				obj[4] = ": ";
				obj[5] = ToString();
				obj[6] = "\tLocal Txn ID = ";
				obj[7] = m_txnLocalID;
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.SinglePhaseCommit, array);
			}
			try
			{
				if (m_state == RMTxnState.Enlisted)
				{
					m_state = RMTxnState.Preparing;
					m_RMWorker.SinglePhaseEvent += doSinglePhaseCommit;
					m_RMWorker.OnSinglePhase(new OnSinglePhaseEventArgs(singlePhaseEnlistment));
				}
				else
				{
					singlePhaseEnlistment.Done();
				}
			}
			catch (Exception ex)
			{
				try
				{
					OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.SinglePhaseCommit, ex);
				}
				catch
				{
				}
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					string[] array2 = new string[1];
					string[] obj3 = new string[8]
					{
						"MTSTxnRM : ",
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					Guid rMGuid = m_RMGuid;
					obj3[1] = rMGuid.ToString();
					obj3[2] = "\tRMState = ";
					obj3[3] = m_state.ToString();
					obj3[4] = ": ";
					obj3[5] = ToString();
					obj3[6] = "\tLocal Txn ID = ";
					obj3[7] = m_txnLocalID;
					array2[0] = string.Concat(obj3);
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.SinglePhaseCommit, array2);
				}
			}
		}

		public void Prepare(PreparingEnlistment preparingEnlistment)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				string[] obj = new string[8]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = "\tLocal Txn ID :";
				obj[3] = m_txnLocalID;
				obj[4] = "\tRMState = ";
				obj[5] = m_state.ToString();
				obj[6] = ": ";
				obj[7] = ToString();
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Prepare, array);
			}
			try
			{
				if (m_state == RMTxnState.Enlisted)
				{
					m_state = RMTxnState.Preparing;
					m_RMWorker.PrepareEvent += doPrepare;
					m_RMWorker.OnPrepare(new OnPrepareEventArgs(preparingEnlistment));
				}
				else
				{
					preparingEnlistment.Done();
				}
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					string[] array2 = new string[1];
					string[] obj2 = new string[8]
					{
						"MTSTxnRM : ",
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					Guid rMGuid = m_RMGuid;
					obj2[1] = rMGuid.ToString();
					obj2[2] = "\tLocal Txn ID:";
					obj2[3] = m_txnLocalID;
					obj2[4] = "\tRMState = ";
					obj2[5] = m_state.ToString();
					obj2[6] = ": ";
					obj2[7] = ToString();
					array2[0] = string.Concat(obj2);
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Prepare, array2);
				}
			}
		}

		public void Commit(Enlistment enlistment)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				string[] obj = new string[8]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = "\tRMState = ";
				obj[3] = m_state.ToString();
				obj[4] = ": ";
				obj[5] = ToString();
				obj[6] = "\tLocal Txn ID = ";
				obj[7] = m_txnLocalID;
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Commit, array);
			}
			try
			{
				if (m_state == RMTxnState.Prepared_ToCommit)
				{
					m_state = RMTxnState.Committing;
					m_RMWorker.CommitEvent += doCommit;
					m_RMWorker.OnCommit(new OnCommitEventArgs(enlistment));
				}
				else
				{
					enlistment.Done();
				}
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					string[] array2 = new string[1];
					string[] obj2 = new string[8]
					{
						"MTSTxnRM : ",
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					Guid rMGuid = m_RMGuid;
					obj2[1] = rMGuid.ToString();
					obj2[2] = "\tRMState = ";
					obj2[3] = m_state.ToString();
					obj2[4] = ": ";
					obj2[5] = ToString();
					obj2[6] = "\tLocal Txn ID = ";
					obj2[7] = m_txnLocalID;
					array2[0] = string.Concat(obj2);
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Commit, array2);
				}
			}
		}

		public void Rollback(Enlistment enlistment)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				string[] obj = new string[8]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = "\tRMState = ";
				obj[3] = m_state.ToString();
				obj[4] = ": ";
				obj[5] = ToString();
				obj[6] = "\tLocal Txn ID = ";
				obj[7] = m_txnLocalID;
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Rollback, array);
			}
			try
			{
				if (m_state == RMTxnState.Enlisted || m_state == RMTxnState.Prepared_Failed || m_state == RMTxnState.Commit_Failed || m_state == RMTxnState.Prepared_ToCommit)
				{
					m_state = RMTxnState.RollingBack;
					m_RMWorker.AbortEvent += doAbort;
					m_RMWorker.OnAbort(new OnAbortEventArgs(enlistment));
				}
				else
				{
					enlistment.Done();
				}
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					string[] array2 = new string[1];
					string[] obj2 = new string[8]
					{
						"MTSTxnRM : ",
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					Guid rMGuid = m_RMGuid;
					obj2[1] = rMGuid.ToString();
					obj2[2] = "\tRMState = ";
					obj2[3] = m_state.ToString();
					obj2[4] = ": ";
					obj2[5] = ToString();
					obj2[6] = "\tLocal Txn ID = ";
					obj2[7] = m_txnLocalID;
					array2[0] = string.Concat(obj2);
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.Rollback, array2);
				}
			}
		}

		public void InDoubt(Enlistment enlistment)
		{
			enlistment.Done();
		}

		private RMTxnState doPrepare()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				string[] obj = new string[6]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = "\tRMState = ";
				obj[3] = m_state.ToString();
				obj[4] = ": ";
				obj[5] = ToString();
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, array);
			}
			RMTxnState result = RMTxnState.Prepared_ReadOnly;
			try
			{
				TxnState txnState = TxnState.Error;
				for (int i = 0; i < m_txnBranches.Count; i++)
				{
					MTSTxnBranch mTSTxnBranch = m_txnBranches[i];
					if (!mTSTxnBranch.IsInTxn)
					{
						continue;
					}
					try
					{
						switch (mTSTxnBranch.Prepare())
						{
						case TxnState.Error:
							return m_state = (result = RMTxnState.Prepared_Failed);
						case TxnState.K2CMDrqcommit:
							result = (m_state = RMTxnState.Prepared_ToCommit);
							break;
						}
					}
					catch (Exception ex)
					{
						OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268439552, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, ex);
						throw;
					}
				}
				return result;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					string[] array2 = new string[1];
					string[] obj2 = new string[6]
					{
						"MTSTxnRM : ",
						null,
						null,
						null,
						null,
						null
					};
					Guid rMGuid = m_RMGuid;
					obj2[1] = rMGuid.ToString();
					obj2[2] = "\tRMState = ";
					obj2[3] = m_state.ToString();
					obj2[4] = ": ";
					obj2[5] = ToString();
					array2[0] = string.Concat(obj2);
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, array2);
				}
			}
		}

		private RMTxnState doCommit()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				string[] obj = new string[6]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = "\tRMState = ";
				obj[3] = m_state.ToString();
				obj[4] = ": ";
				obj[5] = ToString();
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doCommit, array);
			}
			if ((DTCDebugConfig.s_DTCDbgEvt & DTCDebugEvent.FAILPHASE2) == DTCDebugEvent.FAILPHASE2)
			{
				m_state = RMTxnState.Commit_Failed;
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doCommit, "DTC Debug Event is set to " + DTCDebugConfig.s_DTCDbgEvt.ToString() + "  Phase 2 of 2pc commit failed intentionally.   TxnID = " + ToString());
				}
				throw new InvalidOperationException("Phase 2 of 2pc commit failed intentionally. " + ToString());
			}
			try
			{
				Exception ex = null;
				for (int i = 0; i < m_txnBranches.Count; i++)
				{
					MTSTxnBranch mTSTxnBranch = m_txnBranches[i];
					if (mTSTxnBranch.IsInTxn)
					{
						try
						{
							mTSTxnBranch.Commit();
						}
						catch (Exception ex2)
						{
							OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268439552, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doCommit, ex2);
							ex = ex2;
						}
					}
				}
				if (ex != null)
				{
					m_state = RMTxnState.Commit_Failed;
					throw ex;
				}
				return m_state = RMTxnState.Committed;
			}
			catch (Exception ex3)
			{
				try
				{
					OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doCommit, ex3);
				}
				catch
				{
				}
				return m_state = RMTxnState.Commit_Failed;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					string[] array2 = new string[1];
					string[] obj3 = new string[6]
					{
						"MTSTxnRM : ",
						null,
						null,
						null,
						null,
						null
					};
					Guid rMGuid = m_RMGuid;
					obj3[1] = rMGuid.ToString();
					obj3[2] = "\tRMState = ";
					obj3[3] = m_state.ToString();
					obj3[4] = ": ";
					obj3[5] = ToString();
					array2[0] = string.Concat(obj3);
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doCommit, array2);
				}
			}
		}

		internal RMTxnState doAbort()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				string[] obj = new string[6]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = "\tRMState = ";
				obj[3] = m_state.ToString();
				obj[4] = ": ";
				obj[5] = ToString();
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doAbort, array);
			}
			try
			{
				Exception ex = null;
				for (int i = 0; i < m_txnBranches.Count; i++)
				{
					MTSTxnBranch mTSTxnBranch = m_txnBranches[i];
					if (mTSTxnBranch.IsInTxn)
					{
						try
						{
							mTSTxnBranch.Abort();
						}
						catch (Exception ex2)
						{
							OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268439552, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doAbort, ex2);
							ex = ex2;
						}
					}
				}
				if (ex != null)
				{
					m_state = RMTxnState.Rollback_Failed;
					throw ex;
				}
				return m_state = RMTxnState.RollingBack;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					string[] array2 = new string[1];
					string[] obj2 = new string[6]
					{
						"MTSTxnRM : ",
						null,
						null,
						null,
						null,
						null
					};
					Guid rMGuid = m_RMGuid;
					obj2[1] = rMGuid.ToString();
					obj2[2] = "\tRMState = ";
					obj2[3] = m_state.ToString();
					obj2[4] = ": ";
					obj2[5] = ToString();
					array2[0] = string.Concat(obj2);
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doAbort, array2);
				}
			}
		}

		private void doSinglePhaseCommit(object sender, OnSinglePhaseEventArgs e)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				string[] obj = new string[8]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = "\tRMState = ";
				obj[3] = m_state.ToString();
				obj[4] = ": ";
				obj[5] = ToString();
				obj[6] = "\tLocal Txn ID = ";
				obj[7] = m_txnLocalID;
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, array);
			}
			try
			{
				m_RMWorker.SinglePhaseEvent -= doSinglePhaseCommit;
				RMTxnState state = m_state;
				try
				{
					state = doPrepare();
				}
				catch (Exception ex)
				{
					try
					{
						OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, ex);
					}
					catch
					{
					}
					state = (m_state = RMTxnState.Prepared_Failed);
				}
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, "Prepare phase of doSinglePhaseCommit Result: " + state.ToString() + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
				}
				switch (state)
				{
				case RMTxnState.Prepared_Failed:
					try
					{
						m_state = RMTxnState.RollingBack;
						state = doAbort();
						m_state = RMTxnState.RollingBack;
						e.Enlistment.Aborted();
					}
					catch (Exception ex2)
					{
						try
						{
							OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, ex2);
						}
						catch
						{
						}
						if (ProviderConfig.m_bTraceLevelPrivate)
						{
							Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, "Abort() phase of doSinglePhaseCommit failed Result: " + state.ToString() + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
						}
						m_state = RMTxnState.Rollback_Failed;
						try
						{
							e.Enlistment.Aborted(ex2);
						}
						catch
						{
						}
					}
					break;
				case RMTxnState.Prepared_ToCommit:
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, " Committing TxnID = " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
					}
					try
					{
						m_state = RMTxnState.Committing;
						state = doCommit();
						m_state = RMTxnState.Committed;
					}
					catch (Exception ex3)
					{
						try
						{
							OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, ex3);
						}
						catch
						{
						}
						m_state = RMTxnState.Commit_Failed;
						try
						{
							if (ProviderConfig.m_bTraceLevelPrivate)
							{
								Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, " Committed failed.  Send InDoubt Ack for TxnID = " + ToString());
							}
							e.Enlistment.InDoubt(ex3);
						}
						catch
						{
						}
					}
					if (state == RMTxnState.Committed)
					{
						m_state = RMTxnState.Committed;
						e.Enlistment.Committed();
						break;
					}
					m_state = RMTxnState.Commit_Failed;
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, " Committed failed.  Send InDoubt Ack for TxnID = " + ToString());
					}
					e.Enlistment.InDoubt();
					break;
				default:
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, " Tranasaction is readonly: TxnID = " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
					}
					m_state = RMTxnState.Prepared_ReadOnly;
					e.Enlistment.Committed();
					break;
				}
			}
			catch (Exception ex4)
			{
				try
				{
					OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, ex4);
				}
				catch
				{
				}
			}
			finally
			{
				UnRegisteringTxnEvent(m_sysTxn);
				try
				{
					ReleaseRM();
				}
				catch
				{
				}
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					string[] array2 = new string[1];
					string[] obj9 = new string[8]
					{
						"MTSTxnRM : ",
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					Guid rMGuid = m_RMGuid;
					obj9[1] = rMGuid.ToString();
					obj9[2] = "\tRMState = ";
					obj9[3] = m_state.ToString();
					obj9[4] = " : ";
					obj9[5] = ToString();
					obj9[6] = "\tLocal Txn ID = ";
					obj9[7] = m_txnLocalID;
					array2[0] = string.Concat(obj9);
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doSinglePhaseCommit, array2);
				}
			}
		}

		private void doPrepare(object sender, OnPrepareEventArgs e)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, "RMState = " + m_state.ToString() + ": " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
			}
			try
			{
				m_RMWorker.PrepareEvent -= doPrepare;
				try
				{
					m_state = doPrepare();
				}
				catch (Exception ex)
				{
					try
					{
						OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, ex);
					}
					catch
					{
					}
					m_state = RMTxnState.Prepared_Failed;
				}
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, " MTSTxnRM.doPrepare() result:" + m_state.ToString() + " " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
				}
				if (m_state == RMTxnState.Prepared_ToCommit)
				{
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, " MTSTxnRM.doPrepare: Prepared " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
					}
					e.Enlistment.Prepared();
					return;
				}
				if (m_state == RMTxnState.Prepared_ReadOnly)
				{
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, " MTSTxnRM.doPrepare: ReadOnly " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
					}
					e.Enlistment.Done();
					return;
				}
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, " MTSTxnRM.doPrepare: ForceRollback " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
				}
				m_state = RMTxnState.Prepared_Failed;
				e.Enlistment.ForceRollback();
				try
				{
					m_state = RMTxnState.RollingBack;
					m_state = doAbort();
				}
				catch (Exception ex2)
				{
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, " MTSTxnRM.doPrepare:Prepare Failed.  Aborted " + ToString() + Environment.NewLine + ex2.Message);
					}
					m_state = RMTxnState.Rollback_Failed;
				}
			}
			catch (Exception ex3)
			{
				OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, ex3);
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, " MTSTxnRM.doPrepare()-Finally Block: State=" + m_state.ToString() + " MTSTxnRM ID=" + ToString());
				}
				if (m_state == RMTxnState.Prepared_ReadOnly || m_state == RMTxnState.Prepared_Failed || m_state == RMTxnState.Rollback_Failed || m_state == RMTxnState.RollingBack)
				{
					UnRegisteringTxnEvent(m_sysTxn);
					try
					{
						ReleaseRM();
					}
					catch
					{
					}
				}
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					string[] array = new string[1];
					string[] obj3 = new string[8]
					{
						"MTSTxnRM : ",
						null,
						null,
						null,
						null,
						null,
						null,
						null
					};
					Guid rMGuid = m_RMGuid;
					obj3[1] = rMGuid.ToString();
					obj3[2] = "\tRMState = ";
					obj3[3] = m_state.ToString();
					obj3[4] = ": ";
					obj3[5] = ToString();
					obj3[6] = "\tLocal Txn ID = ";
					obj3[7] = m_txnLocalID;
					array[0] = string.Concat(obj3);
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doPrepare, array);
				}
			}
		}

		private void doCommit(object sender, OnCommitEventArgs e)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doCommit, "RMState = " + m_state.ToString() + ": " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
			}
			try
			{
				m_RMWorker.CommitEvent -= doCommit;
				if (doCommit() == RMTxnState.Committed)
				{
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doCommit, " MTSTxnRM.doCommit: Committed. TxnID = " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
					}
					m_state = RMTxnState.Committed;
					e.Enlistment.Done();
				}
			}
			catch (Exception ex)
			{
				try
				{
					OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doCommit, ex);
				}
				catch
				{
				}
				m_state = RMTxnState.Commit_Failed;
			}
			finally
			{
				UnRegisteringTxnEvent(m_sysTxn);
				try
				{
					ReleaseRM();
				}
				catch
				{
				}
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doCommit, "RMState = " + m_state.ToString() + " : " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
				}
			}
		}

		private void doAbort(object sender, OnAbortEventArgs e)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				Guid rMGuid = m_RMGuid;
				array[0] = "MTSTxnRM : " + rMGuid.ToString() + "\tLocal Txn ID = " + m_txnLocalID;
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doAbort, array);
			}
			try
			{
				m_RMWorker.AbortEvent -= doAbort;
				m_state = RMTxnState.RollingBack;
				doAbort();
				m_state = RMTxnState.RollingBack;
			}
			catch (Exception ex)
			{
				try
				{
					OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doAbort, ex);
				}
				catch
				{
				}
				m_state = RMTxnState.Rollback_Failed;
			}
			finally
			{
				UnRegisteringTxnEvent(m_sysTxn);
				try
				{
					ReleaseRM();
				}
				catch
				{
				}
				try
				{
					e.Enlistment.Done();
				}
				catch
				{
				}
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.doAbort, "RMState = " + m_state.ToString() + ": " + ToString() + "\tLocal Txn ID = " + m_txnLocalID);
				}
			}
		}

		internal void EnlistToSysTransaction()
		{
			if (ProviderConfig.m_bTraceLevelPrivate_NoTrace)
			{
				string[] array = new string[1];
				Guid rMGuid = m_RMGuid;
				array[0] = "MTSTxnRM : " + rMGuid.ToString() + " RMState = " + m_state;
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.EnlistToSysTransaction, array);
			}
			try
			{
				if (m_enlistedState != EnlistedState.Local)
				{
					return;
				}
				lock (m_lock)
				{
					if (m_enlistedState == EnlistedState.Local)
					{
						m_sysTxn.EnlistDurable(m_RMGuid, this, EnlistmentOptions.None);
						m_enlistedState = EnlistedState.Distributed;
					}
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.EnlistToSysTransaction, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate_NoTrace)
				{
					string[] array2 = new string[1];
					Guid rMGuid = m_RMGuid;
					array2[0] = "MTSTxnRM : " + rMGuid.ToString() + " RMState = " + m_state;
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.EnlistToSysTransaction, array2);
				}
			}
		}

		internal TxnBranchesByDBInst GetFreeBranches(ConnectionString cs)
		{
			return m_freeTxnBranches.m_freeBranchesByUserAuth[cs.UserAuthenticationString];
		}

		internal MTSTxnBranch GetTxnBranch(ConnectionString cs, string dbInst)
		{
			MTSTxnBranch t = null;
			if (m_NotUsedBranches.Dequeue(out t))
			{
				return t;
			}
			if (!m_freeTxnBranches.DequeueBranch(cs, dbInst, out t))
			{
				lock (m_branchLock)
				{
					if (m_branchNum > MaxNumOfBranches)
					{
						if (m_freeTxnBranches.Count == 0)
						{
							if (ProviderConfig.m_bTraceLevelPrivate)
							{
								Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.GetTxnBranch, Trace.GetCPInfo(null, null, null, "UnableToEnlist4") + " max num of branches reached");
							}
							throw new OracleException(ResourceStringConstants.CON_MTS_ENLIST_FAIL, string.Empty, string.Empty, OracleStringResourceManager.GetErrorMesg(ResourceStringConstants.CON_MTS_ENLIST_FAIL));
						}
						return null;
					}
					t = MTSTxnBranch.CreateTxnBranch(m_bIsCCP, this, m_branchNum);
					m_branchNum++;
					return t;
				}
			}
			return t;
		}

		internal void ReleaseTxnBranch(MTSTxnBranch txnBranch)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				Guid rMGuid = m_RMGuid;
				array[0] = "MTSTxnRM : " + rMGuid.ToString() + "\t TxnID = " + txnBranch.TxnID;
				Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.ReleaseTxnBranch, array);
			}
			if (txnBranch.m_connCreds == null)
			{
				m_NotUsedBranches.Enqueue(txnBranch);
			}
			else
			{
				m_freeTxnBranches.EnqueueBranch(txnBranch);
			}
		}

		internal void FreeTxnBranch(MTSTxnBranch txnBranch)
		{
			if (ProviderConfig.m_bTraceLevelPrivate_NoTrace)
			{
				string[] array = new string[1];
				Guid rMGuid = m_RMGuid;
				array[0] = "MTSTxnRM : " + rMGuid.ToString() + "\t TxnID = " + txnBranch.TxnID;
				Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.FreeTxnBranch, array);
			}
			txnBranch.m_bNew = false;
			m_freeTxnBranches.EnqueueBranch(txnBranch);
		}

		internal void AddBranch(OracleConnectionImpl connImpl, MTSTxnBranch txnBranch, Guid sysTxnXID)
		{
			if (ProviderConfig.m_bTraceLevelPrivate_NoTrace)
			{
				string[] array = new string[1];
				Guid rMGuid = m_RMGuid;
				array[0] = "MTSTxnRM : " + rMGuid.ToString() + "\t TxnID = " + txnBranch.TxnID;
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.AddBranch, array);
			}
			try
			{
				m_txnBranches.AddIfNotExist(txnBranch);
				m_connStrs.AddIfNotExist(connImpl.m_cs);
				m_state = RMTxnState.Enlisted;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate_NoTrace)
				{
					string[] array2 = new string[1];
					Guid rMGuid = m_RMGuid;
					array2[0] = "MTSTxnRM : " + rMGuid.ToString() + "\t TxnID = " + txnBranch.TxnID;
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.AddBranch, array2);
				}
			}
		}

		internal void DetachBranches()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				string[] array = new string[1];
				string[] obj = new string[6]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj[1] = rMGuid.ToString();
				obj[2] = "\tRMState = ";
				obj[3] = m_state.ToString();
				obj[4] = ": ";
				obj[5] = ToString();
				array[0] = string.Concat(obj);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4352, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.DetachBranches, array);
			}
			try
			{
				for (int i = 0; i < m_txnBranches.Count; i++)
				{
					MTSTxnBranch mTSTxnBranch = m_txnBranches[i];
					if (mTSTxnBranch != null && mTSTxnBranch.State == TxnBranchState.InUse)
					{
						try
						{
							mTSTxnBranch.Detach();
						}
						catch (Exception ex)
						{
							OracleException.HandleError(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.DetachBranches, ex);
						}
					}
				}
			}
			finally
			{
				string[] array2 = new string[1];
				string[] obj2 = new string[6]
				{
					"MTSTxnRM : ",
					null,
					null,
					null,
					null,
					null
				};
				Guid rMGuid = m_RMGuid;
				obj2[1] = rMGuid.ToString();
				obj2[2] = "\tRMState = ";
				obj2[3] = m_state.ToString();
				obj2[4] = ": ";
				obj2[5] = ToString();
				array2[0] = string.Concat(obj2);
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)4608, OracleTraceClassName.MTSTxnRM, OracleTraceFuncName.DetachBranches, array2);
			}
		}

		public override string ToString()
		{
			return $"MTSTxnRM ID = {m_sysTxn.TransactionInformation.DistributedIdentifier}=={m_RMGuid}";
		}
	}
}
